package com.sugon.controller.spare;

import cn.afterturn.easypoi.entity.vo.TemplateExcelConstants;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.afterturn.easypoi.view.PoiBaseView;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.StrUtil;
import com.cait.bpmsuite.api.bpmmodle.BPMWorkItem;
import com.cait.service.rescenter.UserInfo;
import com.sugon.annotation.AutoLog;
import com.sugon.annotation.DataFilter;
import com.sugon.annotation.LimitSubmit;
import com.sugon.annotation.NonBusinessParamValid;
import com.sugon.entity.SparePartRequEntity;
import com.sugon.entity.SysOaProcessEntity;
import com.sugon.entity.SysUserEntity;
import com.sugon.entity.vo.SparePartsNeedsPlanCommitEaParam;
import com.sugon.modules.base.consts.BusModule;
import com.sugon.modules.sparepart.consts.MaterialBaseConst;
import com.sugon.modules.sparepart.consts.SparePartNeedsPlanProgress;
import com.sugon.modules.sparepart.consts.SparePartNeedsPlanType;
import com.sugon.modules.sparepart.model.vo.CommonApproveParamVO;
import com.sugon.modules.sparepart.model.vo.SparePartRequDetailVO;
import com.sugon.modules.sparepart.service.ISparepartNeedsPlanManager;
import com.sugon.modules.sys.service.IResCenterAuthenticator;
import com.sugon.modules.utils.HttpUtil;
import com.sugon.modules.workflow.IWorkFlowManager;
import com.sugon.service.*;
import com.sugon.utils.*;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

/**
 * 备件需求计划Controller
 *
 * @author YuXD
 * @date 2020-11-21 21:28
 */
@Controller
@RequestMapping("sparepartrequ")
public class SparePartRequController {

    @Autowired
    private SparePartRequService sparePartRequService;
    @Autowired
    private ISparepartNeedsPlanManager sparepartNeedsPlanManager;
    @Autowired
    private SparePartRequDetailService sparePartRequDetailService;
    @Autowired
    private SysConfigService configService;
    @Autowired
    private IResCenterAuthenticator resCenterAuthenticator;
    @Resource
    private SysOaProcessService oaProcessService;
    @Resource
    private SysUserService userService;
    @Resource
    private IWorkFlowManager workFlowManager;


    /**
     * 查看、审核备件领料单
     * 1、根据workItemId找到对应的备件领料单ID,从而获取领料单和领料明细
     */

    @RequestMapping("/viewAudit")
    public String infoDetailByWorkItemId(HttpServletRequest request, HttpServletResponse response) {
        if (resCenterAuthenticator.checkIdentityToken(request, response)) {
            String identityToken = resCenterAuthenticator.getIdentityToken(request, response);
            Assert.notBlank(identityToken, "登录令牌不能为空！");
            UserInfo currentUser = resCenterAuthenticator.getUserByToken(identityToken);
            if (currentUser == null) {
                throw new UnknownAccountException(StrUtil.format("无效IdentityToken，获取用户信息失败！", identityToken));
            }
            //由于ERMS有自己的登录系统，需要重新登录下
            Subject subject = ShiroUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(currentUser.getLoginID(), "");
            subject.login(token);
            // 获取OA审批流程ID和审批工作项ID
            String workItemId = request.getParameter("workItemId");
            String procInstId = request.getParameter("procInstId");
            Assert.isFalse(StrUtil.isAllBlank(procInstId, workItemId), "目前只允许OA审批用到该页面");
            // 构建查询参数
            Map<String, String> paramMap = MapUtil.newHashMap();
            paramMap.put("procInstId", procInstId);
            paramMap.put("workItemId", workItemId);
            String queryParam = HttpUtil.buildQueryParam(paramMap);
            // 目前统一跳转到备件需求计划审批详情
            return "/spare/sparePartNeedPlanAuditDetail.html" + queryParam;
        } else {
            // 获取完整的请求地址
            String redirectUrl = HttpUtil.getRequestPath(request);
            //生成认证代理地址并执行重定向跳转
            redirectUrl = resCenterAuthenticator.getLoginAgentUrlByRedrect(redirectUrl);
            return "redirect:" + redirectUrl;
        }
    }

    /**
     * 查看信息,两部分
     * 1、当前审核的进度
     * 2、领料单列表
     */
    @GetMapping("/loadSpNeedsPlanDetail")
    @ResponseBody
    public R loadSpNeedsPlanDetail(@RequestParam(value = "procInstId", required = false) String
                                           procInstId, @RequestParam(value = "workItemId", required = false) String workItemId) {
        Assert.isFalse(StrUtil.isAllBlank(procInstId, workItemId), "目前只允许OA审批用到该页面");
        if (StrUtil.isEmpty(procInstId)) {
            BPMWorkItem workItem = workFlowManager.getWorkItemById(workItemId);
            Assert.notNull(workItem, "非法流程工作项ID：{}！", workItemId);
            procInstId = workItem.getProcInstId();
        }
        // 获取审核记录，需要处理第一次审核的场景
        List<SysOaProcessEntity> auditRecordList = oaProcessService.listByProcInstId(procInstId);
        if (auditRecordList == null) {
            auditRecordList = CollectionUtil.newArrayList();
        }
        // 获取备件需求计划详情
        SparePartRequEntity spNeedsPlan = sparePartRequService.queryByProcInstId(procInstId);
        Assert.notNull(spNeedsPlan);
        // 查询备件需求计划明细
        List<SparePartRequDetailVO> items = sparePartRequDetailService.listByPlanId(spNeedsPlan.getId());
        Assert.isTrue(CollectionUtil.isNotEmpty(items));
        return R.ok().put("detail", spNeedsPlan).put("items", items).put("auditRecordList", auditRecordList);
    }

    /**
     * 备件需求计划审核处理
     */
    @AutoLog(value = "审核", busModule = BusModule.NEEDS_PLAN)
    @LimitSubmit(key = "sparepartsNeedsPlanCheck:%s")
    @NonBusinessParamValid
    @RequestMapping("/check")
    @ResponseBody
    public String check(@Validated CommonApproveParamVO approveParam, BindingResult bindingResult) {
        String directUrl;
        // 获取领料单ID
        String id = approveParam.getId();
        // 校验下是否已添加备件
        List<SparePartRequDetailVO> items = sparePartRequDetailService.listByPlanId(id);
        Assert.isTrue(CollectionUtil.isNotEmpty(items));
        // 校验该工作项是否已审核，如果已审核，那么根据审核情形，跳转到不同页面
        SysOaProcessEntity handledWorkItem = oaProcessService.queryByProcessWorkItemId(approveParam.getWorkItemId());
        if (handledWorkItem != null) {
            if (MaterialBaseConst.AUDIT_PASSED.equals(handledWorkItem.getState())) {
                // 重定向到下一流程
                directUrl = "/BPMClient/bpmdesktop/missionmanage/Missionredirect.jsf?workItemId=" + approveParam.getWorkItemId();
            } else {
                // 审核不通过，回退
                directUrl = "/BPMClient/bpmdesktop/missionmanage/Missionexecute.jsf?workitemId=" + approveParam.getWorkItemId() + "&rollback=true";
            }
        } else {
            directUrl = sparepartNeedsPlanManager.check(approveParam);
        }
        // 返回前端页面需要重定向的地址
        return resCenterAuthenticator.getLoginAgentUrlByRedrect(directUrl);
    }


    /**
     * 校验当前月份的需求是否已编制过
     * 如果编制过需要给用户提示
     */
    @RequestMapping("/checkOrganed")
    @ResponseBody
    public R checkOrganed(@RequestParam Map<String, Object> params) {
        // 获取登录用户所属车间
        String workshop = ShiroUtils.getWorkshop();
        if (StrUtil.isEmpty(workshop)) {
            return R.error("当前用户角色不允许编制需求计划");
        }
        params.put("organId", workshop);
        boolean isExists = sparePartRequService.isExists(params);
        return R.ok().put("isExists", isExists ? 1 : 0);
    }

    @RequestMapping("/list")
//    @RequiresPermissions("sparepartrequ:list")
    @DataFilter(deptAlias = "ORGAN_ID", userAlias = "ORGAN_USER")
    @ResponseBody
    public R list(@RequestParam Map<String, Object> params) {
        /*
            备件需求计划分为过程计划和终版计划
                终版计划：所有业务部门都可以看到，但在需求明细中只可以看到自己的
                过程计划：每个业务部门只可以看到自己提交的过程计划
         */
        String filterSql = MapUtil.getStr(params, "filterSql");
        if (StrUtil.isNotEmpty(filterSql)) {
            filterSql = filterSql.replace("AND", "");
            filterSql = "AND ((" + filterSql + " AND PLAN_TYPE = 'PROCESS') OR (PLAN_TYPE = 'RESULT'))";
            params.put("filterSql", filterSql);
        }
        Query query = new Query(params);
        List<SparePartRequEntity> sparePartRequList = sparePartRequService.queryList(query);
        int total = sparePartRequService.queryTotal(query);
        PageUtils pageUtil = new PageUtils(sparePartRequList, total, query.getLimit(), query.getPage());
        return R.ok().put("page", pageUtil);
    }

    /**
     * 查看信息
     */
    @RequestMapping("/info/{id}")
//    @RequiresPermissions("sparepartrequ:info")
    @ResponseBody
    public R info(@PathVariable("id") String id) {
        SparePartRequEntity sparePartRequ = sparePartRequService.queryObject(id);

        return R.ok().put("sparePartRequ", sparePartRequ);
    }

    /**
     * 保存
     */
    @AutoLog(value = "保存", busModule = BusModule.NEEDS_PLAN)
    @RequestMapping("/save")
    @RequiresPermissions("sparepartrequ:save")
    @ResponseBody
    public R save(@RequestBody SparePartRequEntity sparePartRequ) {
        return sparePartRequService.save(sparePartRequ) > 0 ? R.ok() : R.error();
    }

    @LimitSubmit(key = "perfectRepairRecord:%s")
    @NonBusinessParamValid
    @AutoLog(value = "提交审核", busModule = BusModule.NEEDS_PLAN)
    @RequestMapping("/commitApprove")
    @RequiresPermissions("sparepartrequ:save")
    @ResponseBody
    public R commitApprove(@Validated @RequestBody SparePartsNeedsPlanCommitEaParam commitEaParam, BindingResult bindingResult) {
        // 校验是否存在
        SparePartRequEntity sparePartRequ = sparePartRequService.queryObject(commitEaParam.getId());
        if (sparePartRequ == null) {
            return R.error("备件需求计划不存在，请确认!");
        }
        // 校验是否审核中
        int progress = sparePartRequ.getProgress();
        if (progress != SparePartNeedsPlanProgress.NEW && progress != SparePartNeedsPlanProgress.NOT_PASSED && progress != SparePartNeedsPlanProgress.CANCEL) {
            return R.error("备件需求计划审核中或已通过审核，无需重复提交!");
        }
        // 只可以提交自己编制的需求计划
        if (!sparePartRequ.getOrganUser().equals(ShiroUtils.getUserId())) {
            return R.error("只可以提交自己编制的需求计划!");
        }
        // 校验是否已填充内容e
        List<SparePartRequDetailVO> list = sparePartRequDetailService.queryByPlanCode(sparePartRequ.getPlanCode());
        if (CollectionUtil.isEmpty(list)) {
            return R.error("请在添加需求备件后再提交审核");
        }

        /*
            依次校验车间业务主管或技术室主任、车间经理、制造处PE分管人员 是否存在或者登陆过系统
         */
        String unionId = ShiroUtils.getUnionId();
        Assert.isTrue(StrUtil.isNotEmpty(unionId));
        // 校验车间业务主管或技术室主任
        SysUserEntity zhuguan = userService.queryObject(commitEaParam.getZhuguanshenpiren());
        if (zhuguan == null) {
            return R.error("车间业务主管或技术室主任不存在，请确认!");
        }
        if (StrUtil.isEmpty(zhuguan.getUnionId())) {
            return R.error("车间业务主管或技术室主任未登录过ERMS，不能参与审批，请更换审批人！");
        }
        commitEaParam.setZhuguanshenpirenUnionId(zhuguan.getUnionId());
        // 校验车间经理
        SysUserEntity chejianjingli = userService.queryObject(commitEaParam.getChejianjinglishenpiren());
        if (chejianjingli == null) {
            return R.error("车间经理信息不存在，请确认!");
        }
        if (StrUtil.isEmpty(chejianjingli.getUnionId())) {
            return R.error("车间经理未登录过ERMS，不能参与审批，请更换审批人！");
        }
        commitEaParam.setChejianjinglishenpirenUnionId(chejianjingli.getUnionId());
        // 校验制造处PE
        SysUserEntity zhizaochupe = userService.queryObject(commitEaParam.getZhizaochupeshenpiren());
        if (zhizaochupe == null) {
            return R.error("车间业务主管或技术室主任不存在，请确认!");
        }
        if (StrUtil.isEmpty(zhizaochupe.getUnionId())) {
            return R.error("车间业务主管或技术室主任未登录过ERMS，不能参与审批，请更换审批人！");
        }
        commitEaParam.setZhizaochupeshenpirenUnionId(zhizaochupe.getUnionId());
        return sparepartNeedsPlanManager.commitApprove(commitEaParam) ? R.ok() : R.error("提交失败，请稍后重试!");
    }

    /**
     * 取消领料计划审核
     *
     * @return
     */
    @LimitSubmit(key = "cancelSparepartNeedsPlanEa:%s")
    @AutoLog(value = "取消申请", busModule = BusModule.NEEDS_PLAN)
    @RequestMapping("/cancel")
    @RequiresPermissions("sparepartrequ:save")
    @ResponseBody
    public R cancel(@RequestParam String id) {
        SparePartRequEntity needPlan = sparePartRequService.queryObject(id);
        // 校验领料单是否存在
        if (needPlan == null) {
            return R.error("备件需求计划不存在,请确认!");
        }
        // 只可以取消自己发起的领料单
        if (!ShiroUtils.getUserId().equals(needPlan.getOrganUser())) {
            return R.error("只可以取消自己发起的备件需求计划审核申请！");
        }
        // 已出库、已关闭、已取消的领料单不允许取消
        Integer progress = needPlan.getProgress();
        if (CollectionUtil.newArrayList(SparePartNeedsPlanProgress.PASSED, SparePartNeedsPlanProgress.NEW).contains(progress)) {
            return R.error("需求计划未提交审核或已审批通过，无需取消操作！");
        }
        // 取消领料
        return sparepartNeedsPlanManager.cancel(needPlan) ? R.ok() : R.error();
    }

    /**
     * 删除
     */
    @LimitSubmit(key = "deleteSparePartRequ:%s")
    @AutoLog(value = "删除", busModule = BusModule.NEEDS_PLAN)
    @RequestMapping("/delete")
    @RequiresPermissions("sparepartrequ:delete")
    @ResponseBody
    public R delete(@RequestBody String[] ids) {
        sparePartRequService.deleteBatch(ids);
        return R.ok();
    }

    /**
     * 查看所有列表
     */
    @RequestMapping("/queryAll")
    @ResponseBody
    public R queryAll(@RequestParam Map<String, Object> params) {
        List<SparePartRequEntity> list = sparePartRequService.queryList(params);
        return R.ok().put("list", list);
    }

    /**
     * 终版需求计划项导入
     * 默认只导入一次
     */
    @AutoLog(value = "导入终版计划", busModule = BusModule.NEEDS_PLAN)
    @RequestMapping("/import")
    //@RequiresPermissions("sparepartrequ:import")
    @ResponseBody
    public R importE(@RequestParam("file") MultipartFile file, @RequestParam String planId) throws Exception {
        if (file.isEmpty()) {
            throw new RRException("上传文件不能为空");
        }
        // 只有终版计划才可以执行excel导入
        SparePartRequEntity sparePartNeedsPlan = sparePartRequService.queryObject(planId);
        if (sparePartNeedsPlan == null) {
            return R.error("终版需求计划不存在，请确认！");
        }
        // 暂时去掉
        if (!EnumUtil.equals(SparePartNeedsPlanType.RESULT, sparePartNeedsPlan.getPlanType())) {
            return R.error("只有终版需求计划才可以执行导入操作！");
        }
        // 用最新的需求计划明细替换当前的
        int rows = sparePartRequService.importSparePartNeedsPlanItemList(sparePartNeedsPlan, file);
        return R.ok("成功导入" + rows + "条数据");
    }

    /**
     * 导入备件需求计划：只更新订单生成时间+预计到货时间
     */
    @AutoLog(value = "更新订单生成时间", busModule = BusModule.NEEDS_PLAN)
    @RequestMapping("/updateOrderGenerateTime")
    //@RequiresPermissions("sparepartrequ:import")
    @ResponseBody
    public R updateOrderGenerateTime(@RequestParam("file") MultipartFile file, @RequestParam String planId) throws Exception {
        if (file.isEmpty()) {
            throw new RRException("上传文件不能为空");
        }
        // 只有终版计划才可以执行excel导入
        SparePartRequEntity sparePartNeedsPlan = sparePartRequService.queryObject(planId);
        if (sparePartNeedsPlan == null) {
            return R.error("终版需求计划不存在，请确认！");
        }
        // 暂时去掉
        if (!EnumUtil.equals(SparePartNeedsPlanType.RESULT, sparePartNeedsPlan.getPlanType())) {
            return R.error("只有终版需求计划才可以执行该操作！");
        }
        // 用最新的需求计划明细替换当前的
        int rows = sparePartRequService.updateOrderGenerateTime(sparePartNeedsPlan, file);
        return R.ok("成功更新" + rows + "条备件需求明细数据");
    }

    @AutoLog(value = "导出", busModule = BusModule.NEEDS_PLAN)
    @RequestMapping("/export")
    @ResponseBody
    @RequiresPermissions("sparepartrequ:export")
    public void export(@RequestParam String planIds, ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) {
        // 设置导出EXCEL模板名称
        modelMap.put(TemplateExcelConstants.FILE_NAME, "需求计划审核列表");
        // 设置导出模板参数
        TemplateExportParams templateExportParams = new TemplateExportParams(configService.getPoiTemplatePath() + "sparePartNeedPlanReviewTemplate.xlsx");
        templateExportParams.setColForEach(true);
        modelMap.put(TemplateExcelConstants.PARAMS, templateExportParams);
        // 获取设备维护计划预览模板数据
        Map<String, Object> mapData = MapUtil.newHashMap(1);
        mapData.put("sparePartNeedsItemList", sparePartRequService.queryAllByPlanIds(planIds));
        modelMap.put(TemplateExcelConstants.MAP_DATA, mapData);
        PoiBaseView.render(modelMap, request, response, TemplateExcelConstants.EASYPOI_TEMPLATE_EXCEL_VIEW);
    }

}
